package com.midian.common.filter.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Modifier;
import javassist.NotFoundException;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;

/**
 * 类的信息处理
 * @author Mengfh
 *
 */
public class ClazzMsgUtil {
	
	/**log日志对象*/
	private static final Logger logger = LoggerFactory.getLogger(ClazzMsgUtil.class);
	
	/**
     * 获取方法参数名称
     * @param cm CtMethod对象
     * @return
     */
    private static String[] getMethodParamNames(CtMethod cm) {
        MethodInfo methodInfo = cm.getMethodInfo();
        CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
        LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
        String[] paramNames = null;
        try {
            paramNames = new String[cm.getParameterTypes().length];
        } catch (NotFoundException e) {
        	logger.error(e.getMessage());
        }
        int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
        for (int i = 0; i < paramNames.length; i++) {
            paramNames[i] = attr.variableName(i + pos);
        }
        return paramNames;
    }
	
	/**
     * 获取方法参数名称
     * @param clazz 类的class对象
     * @param methodName 类的方法名称
     * @param paramTypes 方法参数类型集合
     * @return
     */
    public static String[] getMethodParamNames(Class<?> clazz, String methodName, Class<?>[] paramTypes) {
        ClassPool pool = ClassPool.getDefault();
        ClassClassPath classPath = new ClassClassPath(clazz);
        pool.insertClassPath(classPath);
        CtClass cc = null;
        CtMethod cm = null;
        try {
            cc = pool.get(clazz.getName());
            String[] paramTypeNames = new String[paramTypes.length];
            for (int i = 0; i < paramTypes.length; i++) {
                paramTypeNames[i] = paramTypes[i].getName();
            }
            cm = cc.getDeclaredMethod(methodName, pool.get(paramTypeNames));
        } catch (NotFoundException e) {
        	logger.error(e.getMessage());
        }
        return getMethodParamNames(cm);
    }
}
